package com.example.auth.service.impl;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
import org.mindrot.jbcrypt.BCrypt;

/**
 * 密码工具类，用于加密和验证密码
 * 支持新的SHA-256格式和旧的BCrypt格式
 */
public class PasswordUtils {

    private static final String ALGORITHM = "SHA-256";
    private static final int SALT_LENGTH = 16;
    private static final String DELIMITER = ":";

    /**
     * 加密密码（使用新的SHA-256格式）
     * 
     * @param password 需要加密的密码
     * @return 加密后的密码字符串（格式：salt:hash）
     */
    public static String encryptPassword(String password) {
        try {
            // 生成随机盐值
            SecureRandom random = new SecureRandom();
            byte[] salt = new byte[SALT_LENGTH];
            random.nextBytes(salt);
            
            // 将密码和盐值组合并进行哈希
            MessageDigest md = MessageDigest.getInstance(ALGORITHM);
            md.update(salt);
            byte[] hashedPassword = md.digest(password.getBytes(StandardCharsets.UTF_8));
            
            // 将盐值和哈希后的密码转换为Base64编码
            String saltBase64 = Base64.getEncoder().encodeToString(salt);
            String hashBase64 = Base64.getEncoder().encodeToString(hashedPassword);
            
            // 返回格式：salt:hash
            return saltBase64 + DELIMITER + hashBase64;
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("加密算法不可用", e);
        }
    }
    
    /**
     * 验证密码是否匹配
     * 支持BCrypt格式和新的SHA-256格式
     * 
     * @param plainPassword 明文密码
     * @param storedPassword 存储的加密密码
     * @return 密码是否匹配
     */
    public static boolean matches(String plainPassword, String storedPassword) {
        if (plainPassword == null || storedPassword == null) {
            System.out.println("PasswordUtils: plainPassword or storedPassword is null");
            return false;
        }
        
        System.out.println("PasswordUtils: Validating password, stored format: " + 
            (storedPassword.length() > 10 ? storedPassword.substring(0, 10) + "..." : storedPassword));
        
        // 检查是否是BCrypt格式（以$2a$, $2b$, $2y$开头）
        if (storedPassword.startsWith("$2a$") || 
            storedPassword.startsWith("$2b$") || 
            storedPassword.startsWith("$2y$")) {
            System.out.println("PasswordUtils: Detected BCrypt format, using BCrypt validation");
            try {
                boolean result = BCrypt.checkpw(plainPassword, storedPassword);
                System.out.println("PasswordUtils: BCrypt validation result: " + result);
                return result;
            } catch (Exception e) {
                System.out.println("PasswordUtils: BCrypt validation failed with exception: " + e.getMessage());
                return false;
            }
        }
        
        // 检查是否是明文密码（临时兼容）
        if (!storedPassword.contains(DELIMITER)) {
            System.out.println("PasswordUtils: Detected plain text format, using direct comparison");
            boolean result = plainPassword.equals(storedPassword);
            System.out.println("PasswordUtils: Plain text validation result: " + result);
            return result;
        }
        
        // 使用新的SHA-256格式验证
        System.out.println("PasswordUtils: Detected SHA-256 format, using SHA-256 validation");
        try {
            // 分离盐值和哈希密码
            String[] parts = storedPassword.split(DELIMITER, 2);
            if (parts.length != 2) {
                System.out.println("PasswordUtils: Invalid SHA-256 format - wrong number of parts");
                return false;
            }
            
            String saltBase64 = parts[0];
            String storedHashBase64 = parts[1];
            
            // 解码盐值
            byte[] salt = Base64.getDecoder().decode(saltBase64);
            
            // 使用相同的盐值对明文密码进行哈希
            MessageDigest md = MessageDigest.getInstance(ALGORITHM);
            md.update(salt);
            byte[] hashedPassword = md.digest(plainPassword.getBytes(StandardCharsets.UTF_8));
            String hashBase64 = Base64.getEncoder().encodeToString(hashedPassword);
            
            // 比较哈希值
            boolean result = storedHashBase64.equals(hashBase64);
            System.out.println("PasswordUtils: SHA-256 validation result: " + result);
            return result;
        } catch (Exception e) {
            System.out.println("PasswordUtils: SHA-256 validation failed with exception: " + e.getMessage());
            return false;
        }
    }
    
    /**
     * 检查密码是否需要升级（用于支持从旧格式升级到新格式）
     * 
     * @param storedPassword 存储的密码
     * @return 是否需要升级
     */
    public static boolean needsUpgrade(String storedPassword) {
        if (storedPassword == null) {
            return true;
        }
        
        // BCrypt格式的密码需要升级到新格式
        if (storedPassword.startsWith("$2a$") || 
            storedPassword.startsWith("$2b$") || 
            storedPassword.startsWith("$2y$")) {
            return true;
        }
        
        // 明文密码需要升级
        if (!storedPassword.contains(DELIMITER)) {
            return true;
        }
        
        // 新格式的密码不需要升级
        return false;
    }
} 